#include "CEventSystem.h"
#include <iostream>

void CEventSystem::DispatchEvent(CEvent* pEvent)
{
	if( pEvent )
	{
		if( pEvent->GetEventType() > 0 &&
			pEvent->GetEventType() < EV_MAX )
		{
			m_bProcessing = true;
			pair<multimap<int, IListener*>::iterator, multimap<int, IListener*>::iterator> mRange;
			mRange = m_mListeners.equal_range(pEvent->GetEventType());

			for( multimap<int, IListener*>::iterator mIter = mRange.first; ;)
			{
				if( mIter == mRange.second )
					break;
				if( (*mIter).second )
					(*mIter).second->HandleEvent(pEvent);
				++mIter;
			}
			m_bProcessing = false;
		}
	}
}
bool CEventSystem::CheckIfRegistered(int nEventID, IListener* pListener)
{
	bool bIsAlreadyRegistered = false;
	pair<multimap<int, IListener*>::iterator, multimap<int, IListener*>::iterator> mRange;
	mRange = m_mListeners.equal_range(nEventID);
	for( multimap<int, IListener*>::iterator mIter = mRange.first; mIter != mRange.second; mIter++)
	{
		if((*mIter).second == pListener )
		{
			bIsAlreadyRegistered = true;
			break;
		}
	}
	return bIsAlreadyRegistered;
}
CEventSystem* CEventSystem::GetInstance()
{
	static CEventSystem instance;
	return &instance;
}
void CEventSystem::AddListener( int nEventID, IListener* pListener)
{
	//if already created or NULL event, dont bother
	if( nEventID == 18 )
	{
		cout << "18 - " << pListener << endl;
		int x = 0;
	}
	if( !pListener )
		return;
	if( CheckIfRegistered(nEventID, pListener) )
		return;
	m_mListeners.insert(make_pair(nEventID, pListener));
}
void CEventSystem::SendEvent( int nEventID, void* pVoid )
{
	CEvent newEvent(nEventID, pVoid);
	m_vCurEvents.push_back(newEvent);
}
void CEventSystem::UnregisterListener( int nEventID, IListener* pListener)
{
	pair<multimap<int, IListener*>::iterator, multimap<int, IListener*>::iterator> mRange;
	mRange = m_mListeners.equal_range(nEventID);

	for( multimap<int, IListener*>::iterator mIter = mRange.first; mIter != mRange.second; mIter++ )
	{
		//check if pointer == listener
		if( (*mIter).second == pListener )
		{
			(*mIter).second = 0;
			mIter = m_mListeners.erase(mIter);
			
			break;
		}
	}
}
void CEventSystem::RemoveListener( IListener* pListener)
{
	if( m_bProcessing )
	{
		if( pListener )
			m_vToBeRemoved.push_back(pListener);
	}
	else
	{
		multimap<int, IListener*>::iterator mIter = m_mListeners.begin();
		while(mIter != m_mListeners.end()) 
		{
			if( (*mIter).second == pListener )
				mIter = m_mListeners.erase(mIter);
			else
				mIter++;
		}
	}
}
void CEventSystem::ProcessEvents()
{
	while(m_vCurEvents.size())
	{
		if( m_vCurEvents.size() > 0 )
		{
			DispatchEvent(&m_vCurEvents.front());
			if( m_vCurEvents.size() )
				m_vCurEvents.pop_front();
		}

		for( unsigned int i(0); i < m_vToBeRemoved.size(); ++i )
		{
			RemoveListener(m_vToBeRemoved[i]);
		}
		m_vToBeRemoved.clear();
	}
}
void CEventSystem::Clear()
{
	m_vCurEvents.clear();
}
void CEventSystem::Shutdown()
{
	m_mListeners.clear();
}